AngularFirestore 教學 (1) : Document


這一章介紹 Document 的概念,包含:

  • 資料型別的包裝 AngularFirestoreDocument
  • 如何取得單純的資料 .valueChanges()
  • 如何取出資料以外的附帶資訊 .snapshotChanges()

AngularFirestore 裡的文件(Documents)

Cloud Firestore 是一種 NoSQL、文件導向的資料庫。你的資料將以文件 (doctument) 的形式儲存,並以集合 (collection) 的方式管理。每一個文件都是 key-value 的格式。Cloud Firestore 改良自 Realtime Database,更適合小型文件與大量集合。

AngularFirestoreDocument

AngularFirestoreDocument service 是 Firestore SDK 的 DocumentReference 型態的包裝。它是一個泛型的服務,以強型別的方法操作資料流,並以依賴注入的方式使用。

這裡示範取得 item collection 裡面的一個 document。每個 Item 文件裡只有一個 name 的欄位。
"items" : [ "1" : {"name":"item1"} ]

import { Component } from '@angular/core';
import { AngularFirestore, AngularFirestoreDocument } from '@angular/fire/firestore';
import { Observable } from 'rxjs';

export interface Item { name: string; }

@Component({
  selector: 'app-root',
  template: `
    <div>
      {{ (item | async)?.name }}
    </div>
  `
})
export class AppComponent {
  private itemDoc: AngularFirestoreDocument<Item>;
  item: Observable<Item>;
  constructor(private afs: AngularFirestore) {
    this.itemDoc = afs.doc<Item>('items/1');
    this.item = this.itemDoc.valueChanges();
  }
  update(item: Item) {
    this.itemDoc.update(item);
  }
}

使用 AngularFirestore.doc('集合id/文件id').valueChanges() 取回一個文件資料。

泛型

前面提到 AngularFirestoreDocument 可以宣告泛型,所以我們要做一個 Item 接口去接資料。
export interface Item { name: string; } 通常會寫在 shared/Item.ts
然後 afs.doc<Item>('items/1'); 可以用泛型方法。

如果有泛型就可以取得回傳的資料結構:

  getItem() {
      return this.firestore.doc<Item>('item/1').valueChanges(); //return Observable<Item>
  }
//component
  getItem() {
    //return Observable<Item>
    console.log(this.todoService.getItem()); 

    //subscribe Observer 
    this.todoService.getItem().subscribe(data => {console.log(data.name)}); //item1
}

如果沒有泛型:

//service
  getItem() {
      return this.firestore.doc('item/1').valueChanges(); //return Observable<unknown>
  }

這邊做 data.name 會取不到屬性。

//component
  getItem() {
    //return Observable<Unkwon>
    console.log(this.todoService.getItem()); 

    //subscribe Observer 
    this.todoService.getItem().subscribe(data => {console.log(data)}); //{name: "item1"}
}

.valueChanges()

.valueChanges()AngularFirestoreDocument 提供的方法,會回傳 Observable 的文件資料 (data) ,也就是前面範例看到的純資料本身 Observable<Item>

其他資料流的方法都是返回 DocumentChangeAction[]

DocumentChangeAction 包含兩個屬性:type、playload。

interface DocumentChangeAction {
  type: DocumentChangeType;
  payload: DocumentChange;
}

DocumentChangeAction 簡略的結構是這樣:

{
payload:{
    doc:{
        doc:{
            data()
        }
    }
}

純資料本身就是最後的 data()。

通常單純需要文件資料時使用 .valueChanges(),但當需要資料以外的附帶資訊時就不會使用,例如需要處理資料 id。如果要取得更多附帶的資訊就要用 snapshotChanges(),它會返回一個 Observable 的 DocumentChangeAction

操作資料

除了剛剛介紹的讀取,還有:

  • set(data: T) - Destructively updates a document's data.
  • update(data: T) - Non-destructively updates a document's data.
  • delete() - Deletes an entire document. Does not delete any nested collections.

巢狀結構

前面的範例結構是 集合-文件

"items" : [ 
    "1" : {
        "name":"item1"
    }
]

但文件裡當然可以存放陣列結構

"items" : [ 
    "1" : {
        "name":"item1",
        "insideItem":[]
    }
]

這邊提供一個範例:

  constructor(private afs: AngularFirestore) {
    this.userDoc = afs.doc<Item>('user/david');
    this.tasks = this.userDoc.collection<Task>('tasks').valueChanges();
  }

參考資料

#angularfirestore crud #AngularFire Quickstart #Angular #Firebase #Firestore







你可能感興趣的文章

Ruby module: Include、extend 和 prepend

Ruby module: Include、extend 和 prepend

What Type of Laser Engraving Machine Should be Used for Stainless Steel Engraving?

What Type of Laser Engraving Machine Should be Used for Stainless Steel Engraving?

Linux 基本操作

Linux 基本操作






留言討論